package com.caishi.lkx.user.login;

import cn.hutool.core.codec.Base64;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.SM2;
import com.caishi.lkx.user.dto.LoginDto;
import com.caishi.lkx.user.ienum.type.UserChannelType;
import com.caishi.lkx.user.ienum.type.UserType;
import com.caishi.lkx.user.model.LoginInfoModel;
import com.caishi.lkx.user.model.MemberModel;
import com.caishi.lkx.user.service.ILoginInfoService;
import com.caishi.lkx.user.service.IMemberService;
import com.caishi.lkx.user.service.impl.UserServiceImpl;
import com.zzw.common.exception.BizException;
import com.zzw.common.exception.BizRuntimeException;
import com.zzw.common.utils.MD5Util;
import com.caishi.lkx.user.UserResultCode;

import org.bouncycastle.crypto.engines.SM2Engine;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Locale;

/**
 * @author by keray
 * date:2019/8/9 22:04
 */
@Service(value = "usernameLoginService")
class UsernameLoginServiceImpl implements LoginService {
    @Resource
    private ILoginInfoService userLoginService;
    @Resource
    private UserServiceImpl userService;

    @Value("${login.sm2.private-key}")
    private String sm2PrivateKey;

    @Value("${login.sm2.public-key}")
    private String sm2PublicKey;

    private static SM2 sm2 = null;
    @Resource
    private IMemberService memberService;

    @PostConstruct
    public void init() {
        sm2 = new SM2(sm2PrivateKey, sm2PublicKey);
        sm2.setMode(SM2Engine.Mode.C1C2C3);
    }

    @Override
    public LoginInfoModel loginBase(LoginDto loginDto, HttpServletRequest request, HttpServletResponse response) throws BizException {
        LoginInfoModel infoModel = userLoginService.selectLoginInfoUserAccount(loginDto.getUserAccount(), loginDto.getType());
        try {
            checkLoginInfo(infoModel, loginDto);
            MemberModel memberModel = memberService.getById(infoModel.getUserId());
            if (null != memberModel) {
                if (UserChannelType.carsi.equals(memberModel.getChannelType())) {
                    throw new BizRuntimeException(UserResultCode.casiLoginError);
                }
            }
        } catch (BizException e) {
            if (getDtoUserTypes(loginDto).stream().anyMatch(v -> v == UserType.member)) {
                if (e.getCode() == UserResultCode.loginInfoNotFound.getCode() && userService.mobileExits(loginDto.getUserAccount(), null)) {
                    throw new BizException(UserResultCode.notSetPass);
                }
            }
            throw e;
        }
        var databasePass = infoModel.getCertificate();
        var userPass = LoginService.passwordEncryption(loginDto.getCredential());
        var passOk = false;
        // 老数据md5的密码
        if (databasePass.length() == 32)
            passOk = databasePass.equals(MD5Util.MD5Encode(userPass)) || databasePass.equals(MD5Util.MD5Encode(userPass).toUpperCase(Locale.ROOT));
        else passOk = databasePass.equals(userPass);
        if (!passOk) {
            loginFail(infoModel, loginDto);
            throw new BizException(UserResultCode.loginAuthFail);
        }
        return infoModel;
    }

    /**
     * 密码解密
     *
     * @param password
     * @return
     */
    public static String decryptStr(String password) {
        try {
            return new String(Base64.decode(sm2.decrypt(password, KeyType.PrivateKey)));
        } catch (Exception e) {
            return password;
        }
    }

}
